package net.csdn.blog.xzknet.test.flashsharing;

/**
 * 解决伪共享的用例
 * 
 * @author Ken
 */
public final class FalseSharing implements Runnable {
    public final static int NUM_THREADS = 4; // change
    public final static long ITERATIONS = 500L * 1000L * 1000L;
    private final int arrayIndex;

    private static VolatileLong[] longs = new VolatileLong[NUM_THREADS];
    static {
        for (int i = 0; i < longs.length; i++) {
            longs[i] = new VolatileLong();
        }
    }

    public FalseSharing(final int arrayIndex) {
        this.arrayIndex = arrayIndex;
    }

    public static void main(final String[] args) throws Exception {
        System.out.println("VolatileLong解决了伪共享问题.");
        final long start = System.nanoTime();
        runTest();
        System.out.println("持续时间 = " + (System.nanoTime() - start));
    }

    private static void runTest() throws InterruptedException {
        Thread[] threads = new Thread[NUM_THREADS];

        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new FalseSharing(i));
        }
        // 启动所有线程
        for (Thread t : threads) {
            t.start();
        }
        // 等待所有线程停止
        for (Thread t : threads) {
            t.join();
        }
    }

    public void run() {
        long i = ITERATIONS + 1;
        while (0 != --i) {
            longs[arrayIndex].value = i;
        }
    }

    public final static class VolatileLong {
        /** 前填充：7 个 long = 56 B */
        public volatile long p0, p1, p2, p3, p4, p5, p6;

        /** 真正的值：8 B */
        public volatile long value = 0L;

        /** 后填充：7 个 long = 56 B */
        public volatile long q0, q1, q2, q3, q4, q5, q6;

        /* ---------- 阻止 JIT 消除填充字段 ---------- */
        public long touchPadding() {
            return p0 + p1 + p2 + p3 + p4 + p5 + p6 +
                    q0 + q1 + q2 + q3 + q4 + q5 + q6;
        }
    }
}
